#include "gpio.h"
#include <stdio.h>

int gpio_read_value(const char *chip_label,
                    unsigned int line_offset,
                    int active_low,
                    int *value_out,
                    const char *consumer)
{
    int ret = -1;
    int val = -1;
    const char *cons = (consumer && consumer[0] != '\0') ? consumer : "gpio_read";

    struct gpiod_chip *chip = gpiod_chip_open_by_label(chip_label);
    if (!chip) {
        fprintf(stderr, "open gpiochip by label '%s' failed\n", chip_label ? chip_label : "NULL");
        return -1;
    }

    struct gpiod_line *line = gpiod_chip_get_line(chip, line_offset);
    if (!line) {
        fprintf(stderr, "get line %u failed\n", line_offset);
        gpiod_chip_close(chip);
        return -1;
    }

    unsigned int flags = 0u;
#ifdef GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW
    if (active_low)
        flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
#endif

    if (gpiod_line_request_input_flags(line, cons, flags) != 0) {
        // 兼容环境下尝试无flags的输入申请
        if (gpiod_line_request_input(line, cons) != 0) {
            fprintf(stderr, "request line %u as input failed\n", line_offset);
            gpiod_line_release(line);
            gpiod_chip_close(chip);
            return -1;
        }
    }

    val = gpiod_line_get_value(line);
    if (val < 0) {
        fprintf(stderr, "read line %u value failed\n", line_offset);
        gpiod_line_release(line);
        gpiod_chip_close(chip);
        return -1;
    }

    // 返回逻辑电平：当active_low=1时，对读取值取反
    if (value_out)
        *value_out = active_low ? !val : val;

    ret = 0;

    gpiod_line_release(line);
    gpiod_chip_close(chip);
    return ret;
}

int gpio_write_value(const char *chip_label,
                     unsigned int line_offset,
                     int active_low,
                     int value,
                     const char *consumer)
{
    int ret = -1;
    const char *cons = (consumer && consumer[0] != '\0') ? consumer : "gpio_write";

    struct gpiod_chip *chip = gpiod_chip_open_by_label(chip_label);
    if (!chip) {
        fprintf(stderr, "open gpiochip by label '%s' failed\n", chip_label ? chip_label : "NULL");
        return -1;
    }

    struct gpiod_line *line = gpiod_chip_get_line(chip, line_offset);
    if (!line) {
        fprintf(stderr, "get line %u failed\n", line_offset);
        gpiod_chip_close(chip);
        return -1;
    }

    unsigned int flags = 0u;
#ifdef GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW
    if (active_low)
        flags |= GPIOD_LINE_REQUEST_FLAG_ACTIVE_LOW;
#endif

    int phys_val = active_low ? !value : value;

#ifdef gpiod_line_request_output_flags
    if (gpiod_line_request_output_flags(line, cons, flags, phys_val) != 0) {
        // 兼容环境下尝试无flags的输出申请
        if (gpiod_line_request_output(line, cons, phys_val) != 0) {
            fprintf(stderr, "request line %u as output failed\n", line_offset);
            gpiod_line_release(line);
            gpiod_chip_close(chip);
            return -1;
        }
    }
#else
    // 某些旧版头文件没有 gpiod_line_request_output_flags 宏/声明
    if (flags != 0u) {
        // 若需要 active_low，但无法带flags申请，则退化为普通输出并在值上做逻辑转换
    }
    if (gpiod_line_request_output(line, cons, phys_val) != 0) {
        fprintf(stderr, "request line %u as output failed\n", line_offset);
        gpiod_line_release(line);
        gpiod_chip_close(chip);
        return -1;
    }
#endif

    // 若上面带初始值的申请失败后退化为无初值申请的情形，这里再设一次值
    if (gpiod_line_set_value(line, phys_val) != 0) {
        fprintf(stderr, "set line %u value failed\n", line_offset);
        gpiod_line_release(line);
        gpiod_chip_close(chip);
        return -1;
    }

    ret = 0;
    gpiod_line_release(line);
    gpiod_chip_close(chip);
    return ret;
}
